package com.guyu.plugin.mybatis.config;

import com.guyu.common.web.factory.YmlPropertySourceFactory;
import com.guyu.plugin.mybatis.config.properties.GuyuMybatisProperties;
import com.guyu.plugin.mybatis.entity.BaseDO;
import com.guyu.plugin.mybatis.helper.MybatisFlexHelper;
import com.guyu.plugin.mybatis.listener.BaseDOInsertListener;
import com.guyu.plugin.mybatis.listener.BaseDOUpdateListener;
import com.guyu.plugin.mybatis.listener.FlexExtListener;
import com.guyu.plugin.mybatis.logicdelete.GuyuLogicDeleteProcessor;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.query.QueryColumnBehavior;
import com.mybatisflex.spring.boot.MyBatisFlexCustomizer;
import com.mybatisflex.spring.boot.MybatisFlexAutoConfiguration;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Objects;

/**
 * mybatis-flex配置类
 */
@Slf4j(topic = "sql")
@EnableConfigurationProperties({GuyuMybatisProperties.class})
@AutoConfiguration(before = MybatisFlexAutoConfiguration.class)
@MapperScan("${mybatis-flex.mapper-packages}")
@EnableTransactionManagement(proxyTargetClass = true)
@PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
public class MybatisFlexConfig implements MyBatisFlexCustomizer {

    static {
        QueryColumnBehavior.setIgnoreFunction(QueryColumnBehavior.IGNORE_BLANK);
        QueryColumnBehavior.setSmartConvertInToEquals(true);
    }

    @Resource
    private GuyuMybatisProperties properties;

    @Override
    public void customize(FlexGlobalConfig globalConfig) {
        //主键逻辑删除处理器
        LogicDeleteManager.setProcessor(new GuyuLogicDeleteProcessor());
        //开启审计功能
        AuditManager.setAuditEnable(properties.getAuditEnable());
        // 开启sql打印默认会开启sql审计
        sqlPrint();
        //插入或更新数据自动设置基础信息
        baseDOAutoEnable(globalConfig);
        //其他扩展
        FlexExtListener flexExtListener = MybatisFlexHelper.getExtListener();
        if (Objects.nonNull(flexExtListener)) {
            flexExtListener.customize(globalConfig);
        }
    }


    /**
     * 打印SQL
     */
    private void sqlPrint() {
        if (!properties.getSqlPrint()) {
            return;
        }
        //设置 SQL 审计收集器
        AuditManager.setMessageCollector(auditMessage -> {
                    Long tookTimeMillis = auditMessage.getElapsedTime();
                    String sql = auditMessage.getFullSql();
                    if (tookTimeMillis > 200) {
                        log.warn("Slow sql exec took {} ms >>> {}", tookTimeMillis, sql);
                    } else {
                        log.info("Flex exec sql took {} ms >>> {}", tookTimeMillis, sql);
                    }
                }
        );
    }

    /**
     * 自动填充基础新
     */
    private void baseDOAutoEnable(FlexGlobalConfig globalConfig) {
        if (!properties.getBaseAutoEnable()) {
            return;
        }
        globalConfig.registerInsertListener(new BaseDOInsertListener(), BaseDO.class);
        globalConfig.registerUpdateListener(new BaseDOUpdateListener(), BaseDO.class);
    }

}
